/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "http2_napi.h"
#include "http2_common.h"
#include "napi/http2_constant.h"
#include "ohos_log.h"
#include <cstddef>

RequestCallback* HandleRequestGoway(void *data, int len)
{
    void *swapData = nullptr;
    int errorCode = 0;
    int lastStreamId = 0;
    int fd = 0;
    std::unordered_map<char *, void *> *gowayMap = static_cast<std::unordered_map<char *, void *> *>(data);
    uint8_t *opaqueData = nullptr;
    for (auto it = gowayMap->begin(); it != gowayMap->end(); it++) {
        if (it->first == "opaque_data" && (it->second)) {
            int dataLen = strlen((char *)it->second) + 1;
            if (len >= 0 && len <= MAX_ALLOC_SIZE) {
                opaqueData = (uint8_t *)malloc(dataLen);
                std::copy((uint8_t *)it->second, (uint8_t *)it->second + dataLen, opaqueData);
                swapData = opaqueData;
            }
        }
        if (it->first == "error_code") {
            errorCode = (int)(intptr_t)(reinterpret_cast<int *>(it->second));
        }
        if (it->first == "last_stream_id") {
            lastStreamId = (int)(intptr_t)(reinterpret_cast<int *>(it->second));
        }
        if (it->first == "fd") {
            fd = (int)(intptr_t)(reinterpret_cast<int *>(it->second));
        }
    }
    RequestCallback *requestCallback = new RequestCallback{.errorCode = errorCode,
                                                           .fd = fd,
                                                           .lastStreamId = lastStreamId,
                                                           .data = swapData
                                                           };
    return requestCallback;
}

RequestCallback* HandleRequestCallback(int type, void *data, int len, int reqType)
{
    void *swapData = nullptr;
    char *responseHeaders = nullptr;
    uint8_t *responseDataTrunck = nullptr;
    int errorCode = 0;
    int lastStreamId = 0;
    int fd = 0;
    if (type == HTTP_STREAM_CALLBACK_TYPE_RESPONSE || type == HTTP_STREAM_CALLBACK_TYPE_ERROR ||
        type == HTTP_CALLBACK_TYPE_CLOSE) {
        int allocLen = strlen((char *)data) + 1;
        if (len >= 0 && len <= MAX_ALLOC_SIZE) {
            responseHeaders = (char *)malloc(allocLen);
            std::copy((uint8_t *)data, (uint8_t *)data + allocLen, responseHeaders);
            swapData = responseHeaders;
        }
    }
    if (type == HTTP_STREAM_CALLBACK_TYPE_RESPONSE_DATA_TRUNCK) {
        if (len >= 0 && len <= MAX_ALLOC_SIZE) {
            responseDataTrunck = (uint8_t *)malloc(len + 1);
            std::copy((uint8_t *)data, (uint8_t *)data + len + 1, responseDataTrunck);
            swapData = responseDataTrunck;
        }
    }
    if (type == HTTP_STREAM_CALLBACK_TYPE_GOWAY) {
        RequestCallback *requestGoway = HandleRequestGoway(data, len);
        errorCode =  requestGoway->errorCode;
        fd =  requestGoway->fd;
        lastStreamId =  requestGoway->lastStreamId;
        swapData = requestGoway->data;
    }
    RequestCallback *requestCallback = new RequestCallback{.env = envMessage_,
                                                           .callbackRef = callBackRefMessage_,
                                                           .type = type,
                                                           .errorCode = errorCode,
                                                           .fd = fd,
                                                           .lastStreamId = lastStreamId,
                                                           .data = swapData,
                                                           .dataLen = len,
                                                           .reqType = reqType};
    return requestCallback;
}

void HandleResponseData(RequestCallback *requestCallback, napi_value* dataNV)
{
    if (requestCallback->type == HTTP_STREAM_CALLBACK_TYPE_RESPONSE ||
        requestCallback->type == HTTP_STREAM_CALLBACK_TYPE_ERROR ||
        requestCallback->type == HTTP_CALLBACK_TYPE_CLOSE) {
        napi_create_string_utf8(requestCallback->env, (char *)requestCallback->data, NAPI_AUTO_LENGTH, dataNV);
    }
    if (requestCallback->type == HTTP_STREAM_CALLBACK_TYPE_RESPONSE_DATA_TRUNCK) {
        if (requestCallback->reqType == 1 && requestCallback->dataLen >= NUM_8) {
            uint8_t *tempData = (uint8_t *)requestCallback->data;
            size_t startIndex = INDEX_5;
            size_t copyLength =  requestCallback->dataLen - INDEX_5;
            if (copyLength > MAX_ALLOC_SIZE || copyLength < 0) {
                return;
            }
            uint8_t *clippedData = (uint8_t *)malloc(copyLength);
            std::copy(tempData + startIndex, tempData + startIndex + copyLength, clippedData);
            CreateArrayBuffer(requestCallback->env, clippedData, copyLength, dataNV);
            if (clippedData) {
                free(clippedData);
                clippedData = nullptr;
            }
        } else {
            CreateArrayBuffer(requestCallback->env, requestCallback->data, requestCallback->dataLen, dataNV);
        }
    }
    if (requestCallback->type == HTTP_STREAM_CALLBACK_TYPE_GOWAY) {
        std::string opaqueData = "";
        if (requestCallback->data) {
            opaqueData = reinterpret_cast<char *>(requestCallback->data);
        }
        nlohmann::json jsonGoWay = nlohmann::json{
            {"error_code", requestCallback->errorCode},
            {"last_stream_id", requestCallback->lastStreamId},
            {"fd", requestCallback->fd},
            {"opaque_data", (char *)opaqueData.c_str()},
        };
        napi_create_string_utf8(requestCallback->env, (char *)jsonGoWay.dump().c_str(), NAPI_AUTO_LENGTH,
            dataNV);
    }
}

void HandleWrite(RequestTask *requestTask)
{
    int fd = requestTask->fd;
    LOGE("napi-->Write req fd :%d", fd);
    struct Connection connection;
    connection.host = requestTask->host;
    connection.path = requestTask->path;
    int rv = HandleSSLShake(&connection, fd, requestTask->host);
    if (rv < 0) {
        LOGE("HandleSSLShake Error fd :%d", fd);
        return;
    }
    nfds_t npollfds = 1;
    struct pollfd pollfds[1];
    g_connectManagerMap[fd] = &connection;
    SendData(&connection, requestTask->buff, requestTask->buffLen);
    pollfds[0].fd = requestTask->fd;
    CtlPoll(pollfds, connection.session, connection.wantIo);
    while (nghttp2_session_want_read(connection.session) || nghttp2_session_want_write(connection.session)) {
        if (fd < 0 || IsDestroyed(fd)) {
            break;
        }
        int nfds = poll(pollfds, npollfds, -1);
        if (nfds == -1) {
            LOGE("poll %s", strerror(errno));
        }
        if (pollfds[0].revents & (POLLIN | POLLOUT)) {
            int res = HandleIo(connection.session, fd);
            if (res < 0) {
                break;
            }
        }
        if ((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
            LOGE("nghttp2_session_want_read error");
            break;
        }
        CtlPoll(pollfds, connection.session, connection.wantIo);
    }
    if (IsDestroyed(fd)) {
        return;
    }
    g_freeManagerMap[fd] = true;
    sleep(1);
    FreeResource(&connection);
}

void HandleEnd(void *data)
{
    Connection *connection = (Connection *)data;
    time_t startTime = time(nullptr);
    while (g_streamCloseManagerMap.find(connection->fd) == g_streamCloseManagerMap.end()) {
        for (const auto &child : g_streamCloseManagerMap) {
            if (child.first == connection->fd) {
                break;
            }
        }
        LOGE("streamCloseManagerMap find %d", connection->fd);
        usleep(NUM_100);
        time_t currentTime = time(nullptr);
        // 10秒之后如果没有检测到close 直接退出
        if (TimeDifference(startTime, currentTime) > NUM_10) {
            break;
        }
    }
    // 等待服务器彻底关闭
    sleep(NUM_3);
    if (g_freeManagerMap.find(connection->fd) != g_freeManagerMap.end()) {
        LOGE("freeManagerMap find success");
        return;
    }
    g_freeManagerMap[connection->fd] = true;
    FreeResource(connection);
}

void OnEventListener(int type, void *data, int len, int reqType)
{
    RequestCallback *requestCallback = HandleRequestCallback(type, data, len, reqType);
    uv_loop_s *loopMessage = nullptr;
    napi_get_uv_event_loop(envMessage_, &loopMessage);
    if (loopMessage == nullptr) {
        LOGE("napi-->loopMessage null");
        return;
    }
    uv_work_t *work = new (std::nothrow) uv_work_t;
    if (work == nullptr) {
        LOGE("napi-->work null");
        return;
    }
    work->data = requestCallback;
    uv_queue_work(
        loopMessage, work, [](uv_work_t *work) {},
        [](uv_work_t *work, int status) {
            LOGI("napi-->uv_queue_work");
            RequestCallback *requestCallback = (RequestCallback *)(work->data);
            napi_value typeNV;
            napi_value dataNV;
            napi_create_int32(requestCallback->env, requestCallback->type, &typeNV);
            HandleResponseData(requestCallback, &dataNV);
            napi_value ret = 0;
            napi_value callback = nullptr;
            napi_get_reference_value(requestCallback->env, requestCallback->callbackRef, &callback);
            if ((requestCallback->type != HTTP_STREAM_CALLBACK_TYPE_END) && dataNV) {
                napi_value argv_2[] = {typeNV, dataNV};
                napi_call_function(requestCallback->env, nullptr, callback, NUM_2, argv_2, &ret);
                if (requestCallback->data && (requestCallback->type != HTTP_STREAM_CALLBACK_TYPE_GOWAY)) {
                    free(requestCallback->data);
                    requestCallback->data = nullptr;
                }
            } else {
                napi_value argv_1[] = {typeNV};
                napi_call_function(requestCallback->env, nullptr, callback, NUM_1, argv_1, &ret);
            }
            if (work != nullptr) {
                delete work;
            }
            delete requestCallback;
            LOGI("napi-->uv_queue_work end");
        });
}

RequestTask* HandleRequestParams(napi_env env, napi_callback_info info)
{
    std::string fdStr;
    std::string host;
    napi_deferred deferred;
    std::string path;
    std::string method;
    std::string contentType;
    size_t argc = PARAM_COUNT_6;
    napi_value args[PARAM_COUNT_6] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, fdStr);
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, host);
    NapiUtil::JsValueToString(env, args[INDEX_2], STR_DEFAULT_SIZE, path);
    NapiUtil::JsValueToString(env, args[INDEX_3], STR_DEFAULT_SIZE, method);
    NapiUtil::JsValueToString(env, args[INDEX_4], STR_DEFAULT_SIZE, contentType);
    int fd = NapiUtil::StringToInt(fdStr);
    napi_value callback = args[INDEX_5];
    napi_ref callBackRefMessage_;
    napi_create_reference(env, callback, 1, &callBackRefMessage_);
    setEnvMessage(env);
    setCallBackRefMessage(callBackRefMessage_);
    MessageCallback(OnEventListener);
    napi_value promise;
    napi_create_promise(env, &deferred, &promise);
    RequestTask *requestTask = new RequestTask{
        .env = env,
        .asyncWork = nullptr,
        .deferred = deferred,
        .fd = fd,
        .host = host,
        .path = path,
        .method = method,
        .contentType = contentType,
        .promise = promise
    };
    g_requestManagerMap[fd] = requestTask;
    return requestTask;
}

int Http2Napi::ConnectTo(const char *host, uint16_t port)
{
    struct addrinfo hints;
    int fd = -1;
    int rv;
    char service[NI_MAXSERV];
    struct addrinfo *res;
    struct addrinfo *rp;
    rv = snprintf_s(service, sizeof(service), sizeof(service), "%u", port);
    if (rv < 0) {
        return -1;
    }
    memset_s(&hints, sizeof(struct addrinfo), 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    rv = getaddrinfo(host, service, &hints, &res);
    if (rv != 0) {
        LOGE("getaddrinfo %s", gai_strerror(rv));
        return -1;
    }
    for (rp = res; rp; rp = rp->ai_next) {
        fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (fd == -1) {
            continue;
        }
        while ((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 && errno == EINTR) {
            if (rv < 0) {
                LOGE("connect rv %d", rv);
            }
        }
        if (rv == 0) {
            break;
        }
        close(fd);
        fd = -1;
    }
    freeaddrinfo(res);
    g_sessionManagerMap[fd] = 0;
    return fd;
}

napi_value Http2Napi::ClassConstructor(napi_env env, napi_callback_info info)
{
    LOGE("napi-->ClassConstructor");
    napi_value targetObj = nullptr;
    size_t argc = PARAM_COUNT_0;
    napi_value args[PARAM_COUNT_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, &targetObj, nullptr);
    Http2Napi *http2Napi = new Http2Napi();
    napi_wrap(
        env, nullptr, http2Napi,
        [](napi_env env, void *data, void *hint) {
            Http2Napi *http2NapiObj = (Http2Napi *)data;
            delete http2NapiObj;
            http2NapiObj = nullptr;
        },
        nullptr, nullptr);
    return targetObj;
}


napi_value Http2Napi::Connect(napi_env env, napi_callback_info info)
{
    LOGE("napi-->Connect");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string host;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, host);
    std::string port;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, port);
    napi_deferred deferred;
    napi_value promise;
    napi_create_promise(env, &deferred, &promise);
    napi_value resourceName;
    napi_create_string_latin1(env, "connect", NAPI_AUTO_LENGTH, &resourceName);
    RequestTask *requestTask =
        new RequestTask{.env = env, .asyncWork = nullptr, .deferred = deferred, .host = host, .port = port};
    napi_create_async_work(
        env, nullptr, resourceName,
        [](napi_env env, void *data) {
            RequestTask *requestTask = (RequestTask *)data;
            LOGE("napi-->Connect start host %s port %s", requestTask->host.c_str(), requestTask->port.c_str());
            int fd = Http2Napi::ConnectTo(requestTask->host.c_str(), NapiUtil::StringToInt(requestTask->port.c_str()));
            LOGE("napi-->Connect fd %d host %s port %s", fd, requestTask->host.c_str(), requestTask->port.c_str());
            requestTask->fd = fd;
            g_reqManagerMap[fd] = true;
        },
        [](napi_env env, napi_status status, void *data) {
            LOGE("napi-->Connect fd success");
            RequestTask *requestTask = (RequestTask *)data;
            napi_value result;
            napi_create_int32(env, requestTask->fd, &result);
            napi_resolve_deferred(requestTask->env, requestTask->deferred, result);
            napi_delete_async_work(env, requestTask->asyncWork);
            delete requestTask;
        },
        requestTask, &requestTask->asyncWork);
    napi_queue_async_work(env, requestTask->asyncWork);
    return promise;
}

napi_value Http2Napi::Request(napi_env env, napi_callback_info info)
{
    LOGE("napi--->Request");
    RequestTask *requestTask = HandleRequestParams(env, info);
    if (g_reqManagerMap.find(requestTask->fd) == g_reqManagerMap.end() || !g_reqManagerMap.at(requestTask->fd)) {
        return nullptr;
    }
    g_reqManagerMap[requestTask->fd] = false;
    napi_value resourceName;
    napi_create_string_latin1(env, "request", NAPI_AUTO_LENGTH, &resourceName);
    napi_create_async_work(
        env, nullptr, resourceName,
        [](napi_env env, void *data) {
            usleep(NUM_1000 * NUM_200);
            RequestTask *requestTask = (RequestTask *)data;
            HandleRequest(requestTask);
        },
        [](napi_env env, napi_status status, void *data) {
            RequestTask *requestTask = (RequestTask *)data;
            napi_value result;
            napi_create_int32(env, requestTask->fd, &result);
            napi_resolve_deferred(requestTask->env, requestTask->deferred, result);
            napi_delete_async_work(env, requestTask->asyncWork);
            delete requestTask;
        },
        requestTask, &requestTask->asyncWork);
    napi_queue_async_work(env, requestTask->asyncWork);
    return requestTask->promise;
}

napi_value Http2Napi::Write(napi_env env, napi_callback_info info)
{
    LOGE("napi--->Write");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string fdStr;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, fdStr);
    void *buffer;
    size_t bufferLen;
    napi_get_arraybuffer_info(env, args[INDEX_1], &buffer, &bufferLen);
    int fd = NapiUtil::StringToInt(fdStr);
    napi_deferred deferred;
    napi_value promise;
    napi_create_promise(env, &deferred, &promise);
    napi_value resourceName;
    napi_create_string_latin1(env, "write", NAPI_AUTO_LENGTH, &resourceName);
    if (g_requestManagerMap.find(fd) == g_requestManagerMap.end()) {
        return promise;
    }
    RequestTask *requestTask = g_requestManagerMap.at(fd);
    if (requestTask->host.size() <= 0 || requestTask->host.size() > NUM_1000) {
        return promise;
    }
    RequestTask *requestTask2 = new RequestTask{.env = env,
                                                .asyncWork = nullptr,
                                                .deferred = deferred,
                                                .host = requestTask->host,
                                                .path = requestTask->path,
                                                .buff = buffer,
                                                .fd = fd,
                                                .buffLen = static_cast<int>(bufferLen)};
    napi_create_async_work(
        env, nullptr, resourceName,
        [](napi_env env, void *data) {
           RequestTask *requestTask = (RequestTask *)data;
           usleep(NUM_1000 * NUM_600);
           HandleWrite(requestTask);
        },
        [](napi_env env, napi_status status, void *data) {
            RequestTask *requestTask = (RequestTask *)data;
            napi_value result;
            napi_create_int32(env, requestTask->fd, &result);
            napi_resolve_deferred(requestTask->env, requestTask->deferred, result);
            napi_delete_async_work(env, requestTask->asyncWork);
            delete requestTask;
        },
        requestTask2, &requestTask2->asyncWork);
    napi_queue_async_work(env, requestTask2->asyncWork);
    return promise;
}

napi_value Http2Napi::End(napi_env env, napi_callback_info info)
{
    LOGI("napi--->End");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string fdStr;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, fdStr);
    int fd = NapiUtil::StringToInt(fdStr);
    auto resIt = g_connectManagerMap.find(fd);
    if (resIt != g_connectManagerMap.end()) {
        LOGE("napi--->End fd %d", fd);
        if (g_sessionManagerMap.at(fd)) {
            return nullptr;
        }
        g_sessionManagerMap[fd] = 1;
        napi_deferred deferred;
        napi_value promise;
        napi_create_promise(env, &deferred, &promise);
        napi_value resourceName;
        napi_create_string_latin1(env, "end", NAPI_AUTO_LENGTH, &resourceName);
        Connection *connection = g_connectManagerMap.at(fd);
        Connection *connection2 = new Connection{.ssl = connection->ssl,
                                                 .fd = fd,
                                                 .sslCtx = connection->sslCtx,
                                                 .env = env,
                                                 .deferred = deferred,
                                                 .session = connection->session};
        napi_create_async_work(
            env, nullptr, resourceName,
            [](napi_env env, void *data) {
               HandleEnd(data);
            },
            [](napi_env env, napi_status status, void *data) {
                Connection *connection = (Connection *)data;
                napi_value result;
                napi_create_int32(env, connection->fd, &result);
                napi_resolve_deferred(connection->env, connection->deferred, result);
                napi_delete_async_work(env, connection->asyncWork);
            },
            connection2, &connection2->asyncWork);
        napi_queue_async_work(env, connection2->asyncWork);
        return promise;
    } else {
        LOGE("Error End");
    }
    return nullptr;
}

napi_value Http2Napi::DnsResolveTxt(napi_env env, napi_callback_info info)
{
    LOGE("napi-->DnsResolveTxt");
    size_t argc = PARAM_COUNT_1;
    napi_value args[PARAM_COUNT_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string host;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, host);
    napi_deferred deferred;
    napi_value promise;
    napi_create_promise(env, &deferred, &promise);
    napi_value resourceName;
    napi_create_string_latin1(env, "DnsResolveTxt", NAPI_AUTO_LENGTH, &resourceName);
    RequestTask *requestTask = new RequestTask{.env = env, .asyncWork = nullptr, .deferred = deferred, .host = host};
    napi_create_async_work(
        env, nullptr, resourceName,
        [](napi_env env, void *data) {
            RequestTask *requestTask = (RequestTask *)data;
            auto result = ResolveHostTxt(requestTask->host);
            for (std::vector<std::string>::iterator it = result.begin(); it != result.end(); ++it) {
                requestTask->dnsText.append(*it);
            }
        },
        [](napi_env env, napi_status status, void *data) {
            LOGE("napi-->DnsResolveTxt success");
            RequestTask *requestTask = (RequestTask *)data;
            napi_value result;
            napi_create_string_utf8(env, requestTask->dnsText.c_str(), NAPI_AUTO_LENGTH, &result);
            napi_resolve_deferred(requestTask->env, requestTask->deferred, result);
            napi_delete_async_work(env, requestTask->asyncWork);
            delete requestTask;
        },
        requestTask, &requestTask->asyncWork);
    napi_queue_async_work(env, requestTask->asyncWork);
    return promise;
}

napi_value Http2Napi::DnsLookup(napi_env env, napi_callback_info info)
{
    LOGE("napi-->DnsLookup");
    size_t argc = PARAM_COUNT_1;
    napi_value args[PARAM_COUNT_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string host;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, host);
    napi_deferred deferred;
    napi_value promise;
    napi_create_promise(env, &deferred, &promise);
    napi_value resourceName;
    napi_create_string_latin1(env, "DnsLookup", NAPI_AUTO_LENGTH, &resourceName);
    RequestTask *requestTask = new RequestTask{.env = env, .asyncWork = nullptr, .deferred = deferred, .host = host};
    napi_create_async_work(
        env, nullptr, resourceName,
        [](napi_env env, void *data) {
            RequestTask *requestTask = (RequestTask *)data;
            requestTask->dnsText = FindIPAddr(requestTask->host);
        },
        [](napi_env env, napi_status status, void *data) {
            LOGE("napi-->DnsLookup success");
            RequestTask *requestTask = (RequestTask *)data;
            napi_value result;
            napi_create_string_utf8(env, requestTask->dnsText.c_str(), NAPI_AUTO_LENGTH, &result);
            napi_resolve_deferred(requestTask->env, requestTask->deferred, result);
            napi_delete_async_work(env, requestTask->asyncWork);
            delete requestTask;
        },
        requestTask, &requestTask->asyncWork);
    napi_queue_async_work(env, requestTask->asyncWork);
    return promise;
}

napi_value Http2Napi::OpenNativeLog(napi_env env, napi_callback_info info)
{
    g_ohosLogOn = true;
    return nullptr;
}